From adb8dd84403917b268556c1c80e81f1b4fcdf7a1 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 14 Jul 2010 16:40:33 +0100 Subject: [PATCH] libxl, xl: exec xenconsole in current process, defer decision to fork to caller Use this to run xenconsole as the foreground process and move the connection to the console in the "create -c" case early enough to be able to view output from the bootloader. This behaviour is consistent with how both "xm console" and "xm create -c" operate. Signed-off-by: Ian Campbell --- tools/libxl/libxl.c | 10 +++---- tools/libxl/libxl.h | 2 +- tools/libxl/xl_cmdimpl.c | 61 +++++++++++++++++++++++++++++----------- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index c89db27678..687a20e106 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -786,12 +786,12 @@ int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force) return 0; } -int libxl_console_attach(struct libxl_ctx *ctx, uint32_t domid, int cons_num) +int libxl_console_exec(struct libxl_ctx *ctx, uint32_t domid, int cons_num) { - char *cmd = libxl_sprintf( - ctx, "%s/xenconsole %d --num %d", - libxl_private_bindir_path(), domid, cons_num); - return (system(cmd) != 0) ? ERROR_FAIL : 0; + char *p = libxl_sprintf(ctx, "%s/xenconsole", libxl_private_bindir_path()); + char *domid_s = libxl_sprintf(ctx, "%d", domid); + char *cons_num_s = libxl_sprintf(ctx, "%d", cons_num); + return execl(p, p, domid_s, "--num", cons_num_s, (void *)NULL) == 0 ? 0 : ERROR_FAIL; } static char ** libxl_build_device_model_args(struct libxl_ctx *ctx, diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 9ca67e826f..67ca8a751d 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -358,7 +358,7 @@ int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid); int libxl_domain_setmaxmem(struct libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb); int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce); -int libxl_console_attach(struct libxl_ctx *ctx, uint32_t domid, int cons_num); +int libxl_console_exec(struct libxl_ctx *ctx, uint32_t domid, int cons_num); int libxl_domain_info(struct libxl_ctx*, struct libxl_dominfo *info_r, uint32_t domid); diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 9706a6a878..090e369712 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -931,12 +931,45 @@ static void *xrealloc(void *ptr, size_t sz) { return r; } +int autoconnect_console(int cons_num) +{ + int status; + pid_t pid, r; + + /* + * Fork for xenconsole. We exec xenconsole in the foreground + * process allowing it to retain the tty. xl continues in the + * child. The xenconsole client uses a xenstore watch to wait for + * the console to be setup so there is no race. + */ + pid = fork(); + if (pid < 0) { + perror("unable to fork xenconsole"); + return ERROR_FAIL; + } else if (pid == 0) + return 0; + + /* + * Catch failure of the create process. + */ + sleep(1); + r = waitpid(pid, &status, WNOHANG); + if (r > 0 && WIFEXITED(status) && WEXITSTATUS(status) != 0) + _exit(WEXITSTATUS(status)); + + libxl_console_exec(&ctx, domid, cons_num); + /* Do not return. xl continued in child process */ + fprintf(stderr, "Unable to attach console\n"); + _exit(1); +} + struct domain_create { int debug; int daemonize; int paused; int dryrun; int quiet; + int console_autoconnect; const char *config_file; const char *extra_config; /* extra config string */ const char *restore_file; @@ -1120,6 +1153,12 @@ start: goto error_out; } + if (dom_info->console_autoconnect) { + ret = autoconnect_console(0); + if (ret) + goto error_out; + } + if (!restore_file || !need_daemon) { if (dm_info.saved_state) { free(dm_info.saved_state); @@ -1467,12 +1506,6 @@ int main_memset(int argc, char **argv) exit(0); } -void console(char *p, int cons_num) -{ - find_domain(p); - libxl_console_attach(&ctx, domid, cons_num); -} - void cd_insert(char *dom, char *virtdev, char *phys) { libxl_device_disk disk; @@ -1570,7 +1603,6 @@ int main_cd_insert(int argc, char **argv) int main_console(int argc, char **argv) { int opt = 0, cons_num = 0; - char *p = NULL; while ((opt = getopt(argc, argv, "hn:")) != -1) { switch (opt) { @@ -1592,10 +1624,10 @@ int main_console(int argc, char **argv) exit(2); } - p = argv[optind]; - - console(p, cons_num); - exit(0); + find_domain(argv[optind]); + libxl_console_exec(&ctx, domid, 0); + fprintf(stderr, "Unable to attach console\n"); + return 1; } void pcilist(char *dom) @@ -2672,7 +2704,6 @@ int main_create(int argc, char **argv) char *filename = NULL; char *p, extra_config[1024]; struct domain_create dom_info; - char dom[10]; /* long enough */ int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0, dryrun = 0, quite = 0; int opt, rc; @@ -2747,16 +2778,12 @@ int main_create(int argc, char **argv) dom_info.config_file = filename; dom_info.extra_config = extra_config; dom_info.migrate_fd = -1; + dom_info.console_autoconnect = console_autoconnect; rc = create_domain(&dom_info); if (rc < 0) exit(-rc); - if (console_autoconnect) { - snprintf(dom, sizeof(dom), "%d", rc); - console(dom, 0); - } - exit(0); } -- 2.30.2